#-*- coding: utf-8 -*-
import os
import sys
import stat

import wx

# Классы различных лексемм
class TexLexer (object):
	'''Базовый класс для всех лексемм. Создавать экземпляр этого класса нельзя '''
	def __init__ (self, position, container, text):
		# Позиция начала лексеммы
		self.position = position
		
		# Текст лексеммы
		self.text = text
		
		# Здесь храним найденные лексеммы
		self.container = container
		
		
	def nextSymbol (self, symbol):
		'''Разобрать следующий символ. Возвращает лексемму, которая будет обрабатывать следующий символ.
		Метод необходимо переопределить в производных классах'''
		raise NotImplementedError ()
		
		
class EmptyLexer (TexLexer):
	'''Пустая лексемма. Нужна в начале списка лексем. Не имеет внутри себя текста (имеет пустой текст)'''
	def __init__ (self, position, container, text):
		TexLexer.__init__ (self, position, container, text)
		
	def nextSymbol (self, symbol):
		self.position += 1
		if symbol == "{":
			newlexer = BeginGroupLexer (self.position, self.container, symbol)
			self.container.append (newlexer)
			return self
			
		elif symbol == "}":
			newlexer = EndGroupLexer (self.position, self.container, symbol)
			self.container.append (newlexer)
			return self
		
		elif symbol == "_":
			newlexer = SubscriptLexer (self.position, self.container, symbol)
			self.container.append (newlexer)
			return self
		
		elif symbol == "^":
			newlexer = SuperscriptLexer (self.position, self.container, symbol)
			self.container.append (newlexer)
			return self	
		
		elif symbol == "\\":
			newlexer = CommandLexer (self.position, self.container, symbol)
			self.container.append (newlexer)
			return newlexer	
			
		else:
			newlexer = ExpressionLexer (self.position, self.container, symbol)
			self.container.append (newlexer)
			return self
		
class ExpressionLexer (TexLexer):
	'''Лексемма для текстовых выражений вида 'abcd', 'a+b * c' и т.д. Без команд, верхних и нижних индексов '''
	def __init__ (self, position, container, text):
		TexLexer.__init__ (self, position, container, text)


class BeginGroupLexer (TexLexer):
	''' Класс лексеммы для открывающейся группы (символ "{" )'''
	def __init__ (self, position, container, text):
		TexLexer.__init__ (self, position, container, text)
		

class EndGroupLexer (TexLexer):
	''' Класс лексеммы для закрывающейся группы (символ "}" )'''
	def __init__ (self, position, container, text):
		TexLexer.__init__ (self, position, container, text)
		

class CommandLexer (TexLexer):
	''' Класс лексеммы команды вида \\abcde '''
	def __init__ (self, position, container, text):
		TexLexer.__init__ (self, position, container, text)
		
	def nextSymbol (self, symbol):
		#print self.text
		
		if symbol == "{":
			newlexer = BeginGroupLexer (self.position + len (self.text), self.container, symbol)
			self.container.append (newlexer)
			return EmptyLexer (self.position + len (self.text), self.container, "")
			
		elif symbol == "}":
			newlexer = EndGroupLexer (self.position + len (self.text), self.container, symbol)
			self.container.append (newlexer)
			return EmptyLexer (self.position + len (self.text), self.container, "")
		
		elif symbol == "_":
			newlexer = SubscriptLexer (self.position + len (self.text), self.container, symbol)
			self.container.append (newlexer)
			return EmptyLexer (self.position + len (self.text), self.container, "")
		
		elif symbol == "^":
			newlexer = SuperscriptLexer (self.position + len (self.text), self.container, symbol)
			self.container.append (newlexer)
			return EmptyLexer (self.position + len (self.text), self.container, "")
		
		elif symbol == "\\":
			newlexer = CommandLexer (self.position + len (self.text), self.container, symbol)
			self.container.append (newlexer)
			return newlexer	
		
		elif symbol.isalpha() or symbol.isdigit():
			self.text += symbol
			return self
			
		else:
			newlexer = ExpressionLexer (self.position + len (self.text), self.container, symbol)
			self.container.append (newlexer)
			return EmptyLexer (self.position + len (self.text), self.container, "")
			
			
class SubscriptLexer (TexLexer):
	''' Класс лексеммы для нижних индексов '''
	def __init__ (self, position, container, text):
		TexLexer.__init__ (self, position, container, text)


class SuperscriptLexer (TexLexer):
	''' Класс лексеммы для верхних индексов '''
	def __init__ (self, position, container, text):
		TexLexer.__init__ (self, position, container, text)
		
		
class TexParser (object):
	''' Разобрать строку на лексеммы'''
	def __init__ (self):
		pass
		
	def parse (self, text):
		lexers = []
		
		curr_lexer = EmptyLexer (-1, lexers, "")
		for symbol in text:
			curr_lexer = curr_lexer.nextSymbol (symbol)
		
		return lexers


class MimeTex (object):
	'''Класс для работы с mimeTex'''
	def __init__ (self, path):
		self.path = path
		
		#self.mimetex_path = os.path.join (self.path, "mimetex.exe")
		#self.mimetex_path = os.path.join (self.path, "mimetex.cgi")
		self.mimetex_path = "./mimetex/mimetex.cgi"
		self.temp_path = "./mimetex/equation.tex"
		self.result_path = "./mimetex/result.gif"
		
		if sys.platform.find ("win") != -1:
			self.mimetex_path = os.path.join (self.path, "mimetex.exe")
			self.temp_path = os.path.join (self.path, "equation.tex")
			self.result_path = os.path.join (self.path, "result.gif")
			
		os.chmod (self.mimetex_path, stat.S_IEXEC)
		
		#print self.mimetex_path
		
		# Кеш для того, чтобы не компилить заново строку, если она не изменилась
		self.prevText = ""
		self.prevImage = None
		
	def compile (self, text, recompile, params = ""):
		"""
		Скомпилировать tex в картинку
		@text - текст, который надо скомпилировать
		@fname - имя файла, куда надо сохранить результат
		@params - дополнительные параметры mimeTex
		"""
		if recompile or text != self.prevText:
			self.prevText = text

			self.compileToFile (text, self.result_path, params)

			if os.path.exists (self.result_path):
				self.prevImage = wx.Image (self.result_path)
			else:
				self.prevImage = None
		
		return self.prevImage


	def compileToFile (self, text, fname, params = ""):
		"""
		Скомпилировать tex в файл
		@text - текст, который надо скомпилировать
		@fname - имя файла, куда надо сохранить результат
		@params - дополнительные параметры mimeTex
		"""
		try:
			# Запишем tex в текстовый файл
			if os.path.exists (self.result_path):
				os.remove (self.result_path)
				
			fp = file (self.temp_path, "w")
			fp.write (text.encode ("1251") )
			fp.close()
		except IOError, e:
			print e
			return
		
		path = '%s -e %s -f  "%s" %s' % (self.mimetex_path, fname, self.temp_path, params)
		
		pipe = os.popen(path)
		pipe.read()
		pipe.close()

	
	def getResultFilename (self):
		return self.result_path
